﻿using GameLibrary.Model;
using GameLibrary.Model.Core;
using GameLibrary.Model.Enums;
using G.Runtime;
using System.Collections.Generic;

namespace GameDesigner.Source.Test
{
    public class MineSweeper
    {
        const string BOMB = "Bomb";
        const string VALUE = "Value";
        
        struct P {
            public int x;
            public int y;
            public P(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }
        
        public static void Build(GameDef game)
        {
            game.Name = "MineSweeper";
            
            List<GameElementDef> elements = new List<GameElementDef>();
            for (int x = 0; x < 4; x++)
            {
                for (int y = 0; y < 4; y++)
                {
                    GameElementDef element = GameDefFactory.Factory.CreateElement(
                        game, new GameLocation(x, y));
                    element.MoveStratagy = MoveStratagyEnum.NO_MOVE;
                    element.Player = "Player1";
                    element.Icon = "Button";
                    game.GameElementDefs.Add(element);
                    {
                        GameValueDef def = new GameValueDef(BOMB, System.TypeCode.Boolean);
                        def.Display = false;
                        element.GameValueDefs.Add(def);
                    }
                    {
                        GameValueDef def = new GameValueDef(VALUE, System.TypeCode.Int32);
                        def.Display = false;
                        element.GameValueDefs.Add(def);
                    }
                    elements.Add(element);
                }
            }
            AssignScript(game);
            AssignBombs(elements);
            AssignValues(game, elements);
            
        }

        static void AssignBombs(List<GameElementDef> elements)
        {
            System.Random r = new System.Random();
            List<GameElementDef> list = new List<GameElementDef>();
            while(list.Count < 5)
            {
                GameElementDef element = elements[r.Next(elements.Count)];
                
                if (list.Contains(element))
                {
                    continue;
                }
                
                GameValueDef def = element.GameValueDefs[BOMB];
                if (def.Value == "true")
                {
                    continue;
                }

                def.Value = "true";
                System.Console.WriteLine(element.Location);
                list.Add(element);
            }
        }
        
        static void AssignValues(GameDef pGameDef, List<GameElementDef> elements)
        {
            foreach (GameElementDef element in elements) 
            {
                List<GameElementDef> neigbors = 
                    GetNeiboringElements(pGameDef, element.Location);
                
                int v = 0;
                foreach (GameElementDef neigbor in neigbors) 
                {
                    GameValueDef bomb = neigbor.GameValueDefs[BOMB];
                    if (bomb.Value == "true")
                    {
                        v += 1;
                    }
                    
                    GameValueDef bombValue = element.GameValueDefs[VALUE];
                    bombValue.Value = "" + v;
                }
            }
        }
        
        static private List<GameElementDef> GetNeiboringElements(GameDef game, GameLocation cursor)
        {
            List<GameLocation> locations = new List<GameLocation>();
            P[] ps = new P[] 
            {
                new P(-1, -1), new P(+0, -1), new P(+1, -1),
                new P(-1, +0), new P(+1, +0),
                new P(-1, +1), new P(+0, +1), new P(+1, +1)
            };

            foreach (P p in ps) 
            {
                GameLocation l = new GameLocation(cursor.X + p.x, cursor.Y + p.y);
                locations.Add(l);
            }
            
            List<GameElementDef> result = new List<GameElementDef>();
            foreach (GameLocation  loc in locations) 
            {
                if (game.GameElementDefs.Contains(loc))
                {
                    GameElementDef def = game.GameElementDefs[loc];
                    result.Add(def);
                }
            }
            
            return result;
        }

        static void AssignScript(GameDef game)
        {
            game.GameElementDefs.GameScriptDef.Text = @"public class ScriptClass
{
    private G.Runtime.GameElements _Subject;

    public ScriptClass(G.Runtime.GameElements subject)
    {
         _Subject = subject;
         _Subject.Triggers.ClickEvent += OnClickEvent;
    }

    void OnClickEvent(G.Runtime.GameElement element)
    {
         element.Icon = """";
         G.Runtime.BooleanGameValue v = (G.Runtime.BooleanGameValue)
             element.GameValues[""Bomb""];
         if (v.Value)
         {
             element.Text = ""BOMB"";
             element.Game.Globals.FireMessage(""You Lose."");
             element.Game.GameController.EndGame();
         }
         else
         {
             G.Runtime.IntGameValue n = (G.Runtime.IntGameValue)
                 element.GameValues[""Value""];
             if (n.Value > 0)
             {
                 element.Text = """" + n.Value;
             }
         }
    }
}
";
        }
    }
}

